#include "Sandbox.cpp"
#include <string.h>

const int com_size = 50;
char COMPILE_CPP[][50] = {"/usr/bin/g++", "-O2", "-std=c++11", "-fno-asm", "-fmax-errors=20", "./Main.cpp", "-o", "./Main"};
char COMPILE_SPJ[][50] = {"/usr/bin/g++", "-O2", "-std=c++11", "-fno-asm", "-fmax-errors=20", "./spj.cpp", "-o", "./spj.out"};
char COMPILE_C[][50] = {"/usr/bin/gcc", "-O2", "-fno-asm", "-fmax-errors=20", "./Main.c", "-o", "./Main"};
char COMPILE_JAVA[][50] = {"/usr/bin/javac", "-encoding", "UTF8", "./Main.java"};
char RUN_C[][50] = {"./Main"};
char RUN_JAVA[][50] = {"/usr/bin/java", "-Xmx1M", "-XX:MaxRAM=1M", "-Djava.security.manager", "-Djava.security.policy=./java.policy", "Main"};


bool compile(int LANG, char* workdir) {
    int ret = -1;
    double time, mem;
    char* compile[20];
    int len;
    switch(LANG) {
        case C:
            len = sizeof(COMPILE_C) / com_size;
            for (int i=0; i<len; ++i) {
                compile[i] = COMPILE_C[i];
            }
            compile[len] = NULL;
            ret = runCommand(COMPILE, (char*)compile[0], (char**)compile, workdir, LANG, 4, 512, time, mem);
            break;
        case CPP:
            len = sizeof(COMPILE_CPP) / com_size;
            for (int i=0; i<len; ++i) {
                compile[i] = COMPILE_CPP[i];
            }
            compile[len] = NULL;
            ret = runCommand(COMPILE, (char*)compile[0], (char**)compile, workdir, LANG, 4, 512, time, mem);
            break;
        case JAVA:
            len = sizeof(COMPILE_JAVA) / com_size;
            for (int i=0; i<len; ++i) {
                compile[i] = COMPILE_JAVA[i];
            }
            compile[len] = NULL;
            ret = runCommand(COMPILE, (char*)compile[0], (char**)compile, workdir, LANG, 8, 2048, time, mem);
            break;
        case CPP_SPJ:
            len = sizeof(COMPILE_SPJ) / com_size;
            for (int i=0; i<len; ++i) {
                compile[i] = COMPILE_SPJ[i];
            }
            compile[len] = NULL;
            ret = runCommand(COMPILE, (char*)compile[0], (char**)compile, workdir, LANG, 8, 512, time, mem);
            break;
        default:
            //bala bala bala
            ;
    }
    if (ret == OJ_OK) return true;
#ifdef LOG
    putLog("compile code: %d\n", ret);
#endif
    return false;
}

int runSolution(int LANG, char* workdir, const int& time_lmt,
        const int& mem_lmt, double& time, double& mem) {
    int ret = -1;
    char* run[20];
    int len;
    switch(LANG) {
        case C:
        case CPP:
            len = sizeof(RUN_C) / com_size;
            for (int i=0; i<len; ++i) {
                run[i] = RUN_C[i];
            }
            run[len] = NULL;
            //第二个参数必须为const char*类型初始化，才能对上SCMP_CMP规则的scmp_datum_t数据段
            ret = runCommand(RUN, (char*)"./Main", (char**)run, workdir, LANG, time_lmt, mem_lmt, time, mem);
            break;
        case JAVA:
            len = sizeof(RUN_JAVA) / com_size;
            for (int i=0; i<len; ++i) {
                run[i] = RUN_JAVA[i];
            }
            run[len] = NULL;
            sprintf(RUN_JAVA[1], "-Xmx%dM", mem_lmt);
            sprintf(RUN_JAVA[2], "-XX:MaxRAM=%dM", mem_lmt);
            exeCmd("cp /etc/java.policy %s/java.policy", workdir);
            //第二个参数必须为const char*类型初始化，才能对上SCMP_CMP规则的scmp_datum_t数据段
            ret = runCommand(RUN, (char*)"/usr/bin/java", (char**)run, workdir, LANG, time_lmt, mem_lmt, time, mem);
            break;
    }
    return ret;
}

int run(int LANG, char* workdir, const int& time_lmt,
        const int& mem_lmt, double& time, double& mem) {
    if (!compile(LANG, workdir)) {
        return OJ_CE;
    }
    int ret = runSolution(LANG, workdir, time_lmt, mem_lmt, time, mem);
    return ret;
}

//int main(int argc, char** argv) {
//    double time, mem;
//    int res = run(JAVA, (char*)"/home/judger/run0/", 2, 256, time, mem);
//    printf("run solution: %d\n", res);
//    printf("time: %fms\n", time);
//    printf("memery: %fM\n", mem);
//    return 0;
//}
